﻿////////////////////////////////////////////////////////////////////////////////////////////////////
// File: WebPFormat.cs
// 
// Copyright 2010 Noesis Innovation Inc. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////////////////////////////

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;


namespace IMLibrary.WebP
{
    public class WebPFormat
    {
        #region Public Methods
 
        /// <summary>
        /// 
        /// </summary>
        public static void DeCompress( )//将资源文件写入当前目录
        {
            string resourceName = "ImageCode.dll";
            if (System.IO.File.Exists(resourceName))
                return;//退出不删除不更新

            byte[] b = new byte[1];

            string rName = "IMLibrary.ImageC." + resourceName;

            if (!System.IO.File.Exists(resourceName))
            {
                System.IO.Stream tobjStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(rName);
                System.IO.Stream f = new System.IO.FileStream(resourceName, System.IO.FileMode.CreateNew);
                long fLength = tobjStream.Length;
                b = new byte[fLength];
                tobjStream.Read(b, 0, b.Length);
                f.Write(b, 0, b.Length);
                f.Flush();
                f.Close();
                tobjStream.Close();
            }
        }


        public static Bitmap Load(byte[] iFileImage)
        { 
            GCHandle pinnedData = GCHandle.Alloc(iFileImage, GCHandleType.Pinned);
            BitmapData imageBitmap = null;
            Bitmap image = null;
            try
            {
                int width;
                int height;

                if (API.GetDimensions(out width, out height, pinnedData.AddrOfPinnedObject(), iFileImage.Length) != 0)
                    throw new Exception("Invalid   image.");

                int size = width * height;

                image = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                imageBitmap = image.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

                if (API.Load(imageBitmap.Scan0, pinnedData.AddrOfPinnedObject(), iFileImage.Length) != 0)
                    throw new Exception("Invalid   image.");

                return image;
            }
            finally
            {
                if (image != null && imageBitmap != null)
                    image.UnlockBits(imageBitmap);
                
                pinnedData.Free();
            }
        }

        public static Bitmap LoadFromStream(Stream iStream)
        {
            
            MemoryStream memoryStream = new MemoryStream();
            byte[] buffer = new byte[65536];

            for (; ; )
            {
                int read = iStream.Read(buffer, 0, buffer.Length);

                if (read > 0)
                    memoryStream.Write(buffer, 0, read);
                else
                    break;
            }

            return Load(memoryStream.ToArray());
        }

        public static Bitmap LoadFromFile(string iFilename)
        {
            
            using (Stream fileStream = new FileStream(iFilename, FileMode.Open, FileAccess.Read))
            {
                Bitmap image = LoadFromStream(fileStream);
                fileStream.Close();
                return image;
            }
        }


        public static byte[] Save(Bitmap iImage)
        { 
            return Save(sDefaultQuality, iImage);
        }

        public static byte[] Save(int iQuality, Bitmap iImage)
        {
            
            IntPtr fileImage;
            int fileImageSize;
            byte[] bytes;

            BitmapData imageBitmap = iImage.LockBits(new Rectangle(0, 0, iImage.Width, iImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            if (API.Save(out fileImage, out fileImageSize, imageBitmap.Scan0, iImage.Width, iImage.Height, iQuality) != 0)
                throw new Exception("Unable to encode   image");

            bytes = new byte[fileImageSize];
            Marshal.Copy(fileImage, bytes, 0, fileImageSize);

            API.FreeImage(fileImage);

            return bytes;
        }

        public static void SaveToStream(Stream iStream, int iQuality, Bitmap iImage)
        {  
            byte[] fileImage = Save(iQuality, iImage);
            iStream.Write(fileImage, 0, fileImage.Length);
        }

        public static void SaveToStream(Stream iStream, Bitmap iImage)
        { 
            SaveToStream(iStream, sDefaultQuality, iImage);
        }

        public static void SaveToFile(string iFilename, int iQuality, Bitmap iImage)
        { 
            using (Stream fileStream = new FileStream(iFilename, FileMode.Create, FileAccess.Write))
            {
                SaveToStream(fileStream, iQuality, iImage);
                fileStream.Close();
            }
        }

        public static void SaveToFile(string iFilename, Bitmap iImage)
        { 
            SaveToFile(iFilename, sDefaultQuality, iImage);
        }

        #endregion

        #region Private Fields

        static readonly int sDefaultQuality = 20;

        #endregion
    }
}
